package net.scratch.netty.util;

import net.scratch.netty.util.PacketBuffer.PacketSize;

/**
 * 
 * @author 'Mystic Flow
 * @author `Discardedx2
 */
public class Packet {

	private final int opcode;
	private final PacketSize size;
	private final byte[] buffer;

	private int pos = 0;

	public Packet(int opcode, PacketSize size, byte[] buffer) {
		this.opcode = opcode;
		this.size = size;
		this.buffer = buffer;
	}

	public int getOpcode() {
		return opcode;
	}

	public PacketSize getSize() {
		return size;
	}

	public byte[] getBuffer() {
		return buffer;
	}

	public int getLength() {
		return buffer.length;
	}

	public byte readByte() {
		if(remaining() >= 1) 
			return buffer[pos++];
		else 
			return 0;
	}

	public int readByteA() {
		return buffer[pos++] - 128;
	}


	public int readByteS() {
		return 128 - buffer[pos++];
	}

	public int readByteC() {
		return -buffer[pos++];
	}

	public int readShort() {
		return (((buffer[pos++] & 0xff) << 8) | (buffer[pos++] & 0xff));
	}

	public int readLEShortA() {
		int i = ((buffer[pos++] - 128 & 0xff)) + ((buffer[pos++] & 0xff) << 8);
		if(i > 32767)
			i -= 0x10000;
		return i;
	}

	public int readShortA() {
		int i = (((buffer[pos++] & 0xff) << 8) + ((buffer[pos++] - 128 & 0xff)));
		if(i > 32767)
			i -= 0x10000;
		return i;
	}

	public int readLEShort() {
		int i = ((buffer[pos++] & 0xff)) + ((buffer[pos++] & 0xff) << 8);
		if(i > 32767)
			i -= 0x10000;
		return i;
	}

	public int readInt() {
		return ((buffer[pos++] & 0xff) << 24)
		| ((buffer[pos++] & 0xff) << 16)
		| ((buffer[pos++] & 0xff) << 8)
		| (buffer[pos++] & 0xff);
	}

	public int readInt1() {
		byte b1 = buffer[pos++];
		byte b2 = buffer[pos++];
		byte b3 = buffer[pos++];
		byte b4 = buffer[pos++];
		return ((b3 << 24) & 0xFF) | ((b4 << 16) & 0xFF) | ((b1 << 8) & 0xFF) | (b2 & 0xFF);
	}


	public int readInt2() {
		int b1 = buffer[pos++] & 0xFF;
		int b2 = buffer[pos++] & 0xFF;
		int b3 = buffer[pos++] & 0xFF;
		int b4 = buffer[pos++] & 0xFF;
		return ((b2 << 24) & 0xFF) | ((b1 << 16) & 0xFF) | ((b4 << 8) & 0xFF) | (b3 & 0xFF);
	}


	public int readLEInt() {
		return (buffer[pos++] & 0xff)
		| ((buffer[pos++] & 0xff) << 8)
		| ((buffer[pos++] & 0xff) << 16)
		| ((buffer[pos++] & 0xff) << 24);
	}

	public long readLong() {
		return ((long) (buffer[pos++] & 0xff) << 56)
		| ((long) (buffer[pos++] & 0xff) << 48)
		| ((long) (buffer[pos++] & 0xff) << 40)
		| ((long) (buffer[pos++] & 0xff) << 32)
		| ((long) (buffer[pos++] & 0xff) << 24)
		| ((long) (buffer[pos++] & 0xff) << 16)
		| ((long) (buffer[pos++] & 0xff) << 8)
		| ((buffer[pos++] & 0xff));
	}

	public String readRS2String() {
		StringBuilder sb = new StringBuilder();
		byte b;
		while((b = buffer[pos++]) != 0) {
			sb.append((char) b);
		}
		return sb.toString();
	}

	public int remaining() {
		return buffer.length - pos;
	}
}
